const fs = require('fs');
import Jimp from 'jimp';


function loadOpenCV(rootDir = '/work', localRootDir = process.cwd()) {
  if(global.Module && global.Module.onRuntimeInitialized && global.cv && global.cv.imread) {
    return Promise.resolve()
  }
  return new Promise(resolve => {
    global.Module = {
      onRuntimeInitialized() {
        // We change emscripten current work directory to 'rootDir' so relative paths are resolved
        // relative to the current local folder, as expected
        global.cv.FS.chdir(rootDir)
        resolve(true)
      },
      preRun() {
        // preRun() is another callback like onRuntimeInitialized() but is called just before the
        // library code runs. Here we mount a local folder in emscripten filesystem and we want to
        // do this before the library is executed so the filesystem is accessible from the start
        const FS = global.Module.FS
        // create rootDir if it doesn't exists
        if(!FS.analyzePath(rootDir).exists) {
          FS.mkdir(rootDir);
        }
        // create localRootFolder if it doesn't exists
        if(!fs.existsSync(localRootDir)) {
          fs.mkdirSync(localRootDir, { recursive: true});
        }
        // FS.mount() is similar to Linux/POSIX mount operation. It basically mounts an external
        // filesystem with given format, in given current filesystem directory.
        FS.mount(FS.filesystems.NODEFS, { root: localRootDir}, rootDir);
      }
    };
    global.cv = require('./../../lib/opencv.js');
  });
}

export default class OpenCvHelper {
  async find(originData, sawData) {
    await loadOpenCV();
    const cv = global.cv;
    const targetColor = await this.rmBg(sawData);

    const iconData = await Jimp.read(originData);
    const img = cv.matFromImageData(iconData.bitmap);

    // 初始化最小差异和最接近位置
    let minDiff = Number.MAX_VALUE;
    let closestPosition = { x: 0, y: 0 };

    // 遍历图像，计算每个像素与目标颜色值的差异
    for (let y = 0; y < img.rows; y++) {
      for (let x = 0; x < img.cols; x++) {
        const pixel = img.ucharPtr(y, x); // 获取像素值
        // console.log(targetColor[0])
        const diff = Math.abs(pixel[0] - targetColor[0]) + 
                    Math.abs(pixel[1] - targetColor[1]) + 
                    Math.abs(pixel[2] - targetColor[2]);

        if (diff < minDiff) {
          minDiff = diff;
          closestPosition.x = x;
          closestPosition.y = y;
        }
      }
    }
    let color = new cv.Scalar(255, 0, 0, 255);
    let minpoint = new cv.Point(closestPosition.x - 40, closestPosition.y - 16);
    let maxpoint = new cv.Point(closestPosition.x + 40, closestPosition.y + 16);
    cv.rectangle(img, minpoint, maxpoint, color, 2, cv.LINE_8, 0);
    // cv.imshow(canvas, img);

    // new Jimp({
    //   width: img.cols,
    //   height: img.rows,
    //   data: Buffer.from(img.data)
    // })
    // .write('output.png');
    return {x: closestPosition.x - 2, y: closestPosition.y - 2};
  }

  async rmBg(sawData) {
    const cv = global.cv;
    
    const iconData = await Jimp.read(sawData);
    let src = cv.matFromImageData(iconData.bitmap);
    cv.cvtColor(src, src, cv.COLOR_RGBA2RGB, 0);
    let mask = new cv.Mat();
    let bgdModel = new cv.Mat();
    let fgdModel = new cv.Mat();
    let rect = new cv.Rect(20, 0, 40, 32);
    cv.grabCut(src, mask, rect, bgdModel, fgdModel, 1, cv.GC_INIT_WITH_RECT);

    let totalPixels = 0;
    let totalB = 0;
    let totalG = 0;
    let totalR = 0;
    for (let i = 0; i < src.rows; i++) {
      for (let j = 0; j < src.cols; j++) {
        if (mask.ucharPtr(i, j)[0] == 0 || mask.ucharPtr(i, j)[0] == 2) {
          src.ucharPtr(i, j)[0] = 0;
          src.ucharPtr(i, j)[1] = 0;
          src.ucharPtr(i, j)[2] = 0;
        } else {
          if (i > 6 && i < 26 && j > 30 && j < 50) {
            totalPixels++;
            const pixel = src.ucharPtr(i, j);
            totalR += pixel[0]; // 蓝色通道值
            totalG += pixel[1]; // 绿色通道值
            totalB += pixel[2]; // 红色通道值
          } else {
            src.ucharPtr(i, j)[0] = 0;
            src.ucharPtr(i, j)[1] = 0;
            src.ucharPtr(i, j)[2] = 0;
          }
        }
      }
    }

    // const denoisedImg = new cv.Mat();
    // new Jimp({
    //   width: src.cols,
    //   height: src.rows,
    //   data: Buffer.from(src.data)
    // })
    // .write('saw.png');
    // 使用高斯模糊对图像进行降噪
    // cv.GaussianBlur(src, denoisedImg, new cv.Size(5, 5), 0, 0, cv.BORDER_DEFAULT);

    // cv.imshow(canvas, denoisedImg);
    src.delete(); 
    mask.delete();
    bgdModel.delete();
    fgdModel.delete();
    const avgB = totalB / totalPixels;
    const avgG = totalG / totalPixels;
    const avgR = totalR / totalPixels;
    return new cv.Scalar(avgR, avgG, avgB, 255);;
  }
}